package com.mbf.crm.handler;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.jboss.logging.Logger;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import com.mbf.crm.common.Constants;
import com.mbf.crm.common.ImUser;
import com.mbf.crm.common.SocketMessage;

/**
 * <p>
 * Copyright © 2010-2017 soho team All Rights Reserved
 * </p>
 * <p>
 * WebSocket实现服务器和客户端消息推送
 * </p>
 * 
 * @author 晏鼠 张劲松
 *
 */
@Component
public class WebSocketHandler extends TextWebSocketHandler {

	// ArrayList<WebSocketSession>users 会出现性能问题，最好用Map存储
	private static final HashMap<Long, WebSocketSession> users;
	private static final Logger logger = Logger
			.getLogger(WebSocketHandler.class);

	static {
		users = new HashMap<Long, WebSocketSession>();
	}

	public WebSocketHandler() {
	}

	/**
	 * 连接成功后，会触发页面上的onopen方法
	 */
	@Override
	public void afterConnectionEstablished(WebSocketSession session)
			throws Exception {
		ImUser member = (ImUser) session.getAttributes().get(
				Constants.WEB_SOCKET_USERNAME);
		users.put(member.getUid(), session);
		System.out.println("Connect to the websocket success...当前数量："
				+ users.size());
		// 成功之后推送给所有人你上线了
		sendMessageToUsers(new SocketMessage("online",member).toTextMessage());
	}
	
	/**
	 * 关闭连接时会触发
	 */
	@Override
	public void afterConnectionClosed(WebSocketSession session,
			CloseStatus closeStatus) throws Exception {
		logger.debug("websocket connection closed...");
		ImUser member = (ImUser) session.getAttributes().get(Constants.WEB_SOCKET_USERNAME);
		System.out.println("用户"+member.getRealName()+"已退出!");
		users.remove(member.getUid());
		System.out.println("剩余在线用户"+users.size());
		//下线
		sendMessageToUsers(new SocketMessage("offline", member).toTextMessage());
	}
	
	/**
	 * js调用websocket.send时候，会调用该方法
	 * @param session
	 * @param message
	 * @throws Exception
	 */
	@Override
	protected void handleTextMessage(WebSocketSession session,
			TextMessage message) throws Exception {
		logger.info("不能主动推送发消息");
	}
	
	@Override
	public void handleTransportError(WebSocketSession session,
			Throwable exception) throws Exception {
		if(session.isOpen()){
			session.close();
		}
		logger.debug("websocket connection closed...");
		ImUser member = (ImUser) session.getAttributes().get(Constants.WEB_SOCKET_USERNAME);
		users.remove(member.getUid());
	}
	
	/**
	 * 给某个用户发送信息
	 */
	public void sendMessageToUser(Long id, TextMessage message) {
		if (users.containsKey(id)) {
			WebSocketSession user = users.get(id);
			try {
				if (user.isOpen()) {
					user.sendMessage(message);
					System.out.println("------------发送消息成功");
				}
			} catch (IOException e) {
				System.out.println("发送消息失败");
				logger.error("发送消息失败");
			}
		}
	}

	/**
	 * 给所有在线用户发送消息
	 * 
	 * @param message
	 */
	public void sendMessageToUsers(TextMessage message) {
		users.entrySet().forEach(entry -> {
			try {
				if (entry.getValue().isOpen()) {
					entry.getValue().sendMessage(message);
				}
			} catch (IOException e) {
				logger.error("群发消息失败！", e);
			}
		});
	}

	/**
	 * 获取所有在线用户
	 * 
	 * @return
	 */
	public List<ImUser> getUsers() {
		List<ImUser> members = new ArrayList<ImUser>();
		users.entrySet().forEach(entry -> {
			if(entry.getValue().isOpen()){
				ImUser member = (ImUser) entry.getValue().getAttributes().get(Constants.WEB_SOCKET_USERNAME);
				members.add(member);
			}
		});
		return members;
	}
	
	/**
	 * 判断用户是否在线
	 * @return
	 */
	public boolean isOnline(Long uid){
		return users.containsKey(uid);
	}
	
	/**
	 * 下线用户
	 * @param uid
	 */
	public void offLine(Long uid){
		try{
			WebSocketSession session = users.remove(uid);
			if(session.isOpen()){
				session.close();
			}
		}catch(IOException e){
			logger.info("用户下线失败！");
		}
	}
	
}
